#pragma once

#include "../im.h"

class MysqlConnectionPool
{
public:
    MysqlConnectionPool(
        size_t size,
        const std::string &host,
        const std::string &user,
        const std::string &pwd,
        const std::string &dbname)
        : size(size), host(host), user(user), pwd(pwd), db(dbname)
    {
        if (size == 0 || size > std::thread::hardware_concurrency())
        {
            size = std::thread::hardware_concurrency();
        }
        for (size_t i = 0; i < size; ++i)
        {
            MYSQL *con = mysql_init(nullptr);
            mysql_real_connect(con, host.c_str(), user.c_str(), pwd.c_str(), db.c_str(), 0, nullptr, 0);
            mysql_options(con, MYSQL_SET_CHARSET_NAME, "utf8");
            my_bool t = 1;
            mysql_options(con, MYSQL_OPT_RECONNECT, &t);
            connections.push_back(con);
        }
    }
    ~MysqlConnectionPool()
    {
        for (auto con : connections)
        {
            mysql_close(con);
        }
    }

    MYSQL *getConnection()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        cv.wait(lock, [this]
                { return !connections.empty(); });
        auto con = connections.back();
        connections.pop_back();
        return con;
    }

    void releaseConnection(MYSQL *con)
    {
        connections.push_back(con);
        // notify_one 只会唤醒一个等待线程
        // notify_all 会唤醒所有等待线程
        cv.notify_one();
    }

private:
    std::vector<MYSQL *> connections;

    std::condition_variable cv;
    std::mutex mutex_;
    size_t size;
    std::string host;
    std::string user;
    std::string pwd;
    std::string db;
};